package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.PaymentWay;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.config.DeadLetterMQConfig;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.rabbitmq.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: Mamba
 * @Description:
 * @Time: 2021/1/8 19:11
 * @version: 1.0
 */
@Service
public class OrderInfoServiceImpl implements OrderInfoService {//等于变相的使用了jdk动态代理
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    //底层使用了Cblib动态代理   可以注入接口也可以注入实现类 代理中是无敌的  性能也最差 跟Jdk动态代理相比
    //jdk动态代理要求实现类必须要有接口，注入的必须是接口。jdk动态代理具有局限性
    //spring框架自动选择，如果注入的是接口，默认使用jdk代理；注入的是实现类，默认使用Cblib代理
    @Autowired
    private RabbitService rabbitService;


    //3:保存订单
    @Override
    @Transactional
    public Long submitOrder(OrderInfo orderInfo) {
    //3.1：保存订单表
        //总金额
        orderInfo.sumTotalAmount();
        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //创建时间
        orderInfo.setCreateTime(new Date());
        // 创建时间 2小时之后 失效时间
        Calendar instance = Calendar.getInstance();//当前时间
        instance.add(Calendar.HOUR,2);//追加2小时
        orderInfo.setExpireTime(instance.getTime());//取出追加后的时间
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //订单交易编号
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis()
                + new Random().nextInt(100);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        for (OrderDetail orderDetail : orderDetailList) {

            sb.append(orderDetail.getSkuName() + " ");
        }
        if(sb.length() > 100){
            orderInfo.setTradeBody(sb.substring(0,100));
        }else{
            orderInfo.setTradeBody(sb.toString());
        }
        //保存订单主表
        orderInfoMapper.insert(orderInfo);
    //3.2:保存订单详情表 多
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
    //3.3删除购物车DB  删除当前提交了订单的购物车中的商品  如果使用远程调用需要注意分布式事务问题
        //        delete from cart_info where user_id = 3 and sku_id in (5,8)
        //////////////////////////////////////////////
        //        delete from cart_info where
        //        (user_id = 3 and sku_id = 5) OR (user_id = 3 and sku_id = 8)
        QueryWrapper<CartInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", orderInfo.getUserId());
        List<String> skuIdList = orderDetailList.stream().map(orderDetail ->
                orderDetail.getSkuId().toString())
                .collect(Collectors.toList());
        queryWrapper.in("sku_id", skuIdList);
        //        for (OrderDetail orderDetail : orderDetailList) {
        //1:用户ID
       /*     queryWrapper.eq("user_id",orderInfo.getUserId());
            //2:库存ID
            queryWrapper.eq("sku_id",orderDetail.getSkuId());
            queryWrapper.or();*/
        //}
        cartInfoMapper.delete(queryWrapper);
    //3.4删除缓存
        redisTemplate.opsForHash().delete(RedisConst.USER_KEY_PREFIX + orderInfo.getUserId()
         + RedisConst.USER_CART_KEY_SUFFIX,skuIdList.toArray());
    // 3.5发消息（延迟消息） 2小时  取消订单 RabbitMQ 面试  死信队列   延迟插件
        rabbitService.sendDeadLetterMessage(DeadLetterMQConfig.EXCHANGE_DIRECT_ORDER_CANCEL,
                DeadLetterMQConfig.ROUTING_ORDER_CANCEL1,orderInfo.getId(),10);

        return orderInfo.getId();
    }


    @Value("${ware.url}")
    private String wareUrl;

    //校验是否有货
    @Override
    public Boolean hasStock(Long skuId, Integer skuNum) {
        //远程调用仓库  仓库接口暴露出来
        // http: Apache  HttpClient  hosts
        String s = HttpClientUtil.doGet(wareUrl + "/hasStock?skuId=" + skuId
                + "&num=" + skuNum);

        return "1".equals(s);
    }

    //获取订单 根据ID
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }


    //取消订单
    @Override
    public void cancelOrder(Long orderId) {
        //幂等性问题
        //1：不能重复提交
        //2：不能修改已支付的订单
        //一.查询订单状态
        //二.订单状态为未支付
        //三.如果是未支付 改成已关闭 否则不做任何操作
        OrderInfo orderInfo = getOrderInfo(orderId);
        if (null !=orderInfo){
            if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
                //取消订单
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
                orderInfoMapper.updateById(orderInfo);
            }
        }
    }


    //折单
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {

        //订单详情表   skuId 1  skuId 5   同一张订单里
        //1:订单主表 原订单是不变了  原订单父订单 产生2张子订单   保存2条新的订单主表
        //2:订单详情表  修改订单主表的外键

        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);

        //原订单
        OrderInfo originOrderInfo = getOrderInfoWithOrderDetail(orderId);
        //原订单详情集合
        List<OrderDetail> originOrderDetailList = originOrderInfo.getOrderDetailList();

        //
        List<OrderInfo> subOrderInfoList = new ArrayList<>();
        //[{"wareId":"1","skuIds":["5","6"]},{"wareId":"2","skuIds":["1"]}]

        for (Map map : mapList) {
            //子订单主表
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(originOrderInfo, subOrderInfo);
            String wareId = (String) map.get("wareId");
            subOrderInfo.setWareId(wareId);
            // 将原来订单的id 设置 null，不使用原订单的主键
            subOrderInfo.setId(null);
            //设置父订单的ID
            subOrderInfo.setParentOrderId(originOrderInfo.getId());

            List<OrderDetail> orderDetailList = new ArrayList<>();


            for (OrderDetail orderDetail : originOrderDetailList) {
                List<String> skuIds = (List<String>) map.get("skuIds");
                for (String skuId : skuIds) {
                    if (skuId.equals(orderDetail.getSkuId())) {
                        //订单详情表  修改订单主表的外键
                        orderDetailList.add(orderDetail);
                    }
                }
            }
            //子订单总金额
            subOrderInfo.setOrderDetailList(orderDetailList);
            subOrderInfo.sumTotalAmount();
            //保存子订单主表
            orderInfoMapper.insert(subOrderInfo);
            //update order_detail set order_id = 16 where id in (x,x,x,)
            //更新子订单详情表 外键（批量)
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(subOrderInfo.getId());
            List<Long> ids = orderDetailList.stream().map(OrderDetail::getId)
                    .collect(Collectors.toList());
            orderDetailMapper.update(orderDetail,new QueryWrapper<OrderDetail>()
                    .in("id",ids));

            //追加子订单结果
            subOrderInfoList.add(subOrderInfo);
        }
        //将原订单的状态改成订单已拆单
        updateOrderStatus(orderId,ProcessStatus.SPLIT);

        return subOrderInfoList;
    }

    private void updateOrderStatus(Long orderId, ProcessStatus split) {

    }
    //MQ 生产端发消息给仓库  构建仓库所有数据

    @Override
    public Map initWareOrder(Long orderId) {
        OrderInfo orderInfo = getOrderInfoWithOrderDetail(orderId);
        //1：Map  订单表信息
        //2: List<Map> 订单详情信息
        //3: Map.put("detail",List<Map> );
        HashMap<String,Object> map = new HashMap<>();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        map.put("paymentWay",orderInfo.getPaymentWay().equals(PaymentWay.ONLINE.name())?"2":"1");
        //
        //map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
        ArrayList<Map> mapArrayList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            mapArrayList.add(orderDetailMap);
        }
        map.put("details",mapArrayList);
        return map;
    }

    @Override
    public Map initWareOrder(OrderInfo orderInfo){
        HashMap<String,Object> map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay",orderInfo.getPaymentWay().equals(PaymentWay.ONLINE.name())?"2":"1");

        map.put("wareId",orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
        ArrayList<Map> mapArrayList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            mapArrayList.add(orderDetailMap);
        }
        map.put("details",mapArrayList);
        return map;
    }

    //查询订单表及详情表
    @Override
    public OrderInfo getOrderInfoWithOrderDetail(Long orderId){
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId));
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }





}
